#include "async_logger.h"

#include "appender.h"
#include "async_thread_pool.h"

namespace afcore {
namespace log {

CAsyncLogger::CAsyncLogger(std::string logger_name, RAppenderInitList appenders, RAsyncThreadPoolWptr tp,
  EAsyncOverflowPolicy overflow_policy)
  : CAsyncLogger(std::move(logger_name), appenders.begin(), appenders.end(), std::move(tp), overflow_policy) {
}

CAsyncLogger::CAsyncLogger(std::string logger_name, RAppenderSptr single_appender, RAsyncThreadPoolWptr tp,
  EAsyncOverflowPolicy overflow_policy)
  : CAsyncLogger(std::move(logger_name), {std::move(single_appender)}, std::move(tp), overflow_policy) {
}

std::shared_ptr<CLogger> CAsyncLogger::CLone(std::string logger_name) {
  auto cloned = std::make_shared<CAsyncLogger>(*this);
  cloned->name_ = std::move(logger_name);
  return cloned;
}

void CAsyncLogger::AppenderDoLog(const SLogMessage &msg) {
  if (auto pool_ptr = thread_pool_.lock()) {
    pool_ptr->PostLog(shared_from_this(), msg, overflow_policy_);
  } else {
    ThrowCLogeException("CAsyncLogger::AppenderDoLog: thread pool does't exist anymore");
  }
}

void CAsyncLogger::DoFlush() {
  if (auto pool_ptr = thread_pool_.lock()) {
    pool_ptr->PostFlush(shared_from_this(), overflow_policy_);
  } else {
    ThrowCLogeException("CAsyncLogger::DoFlush: thread pool does't exist anymore");
  }
}

void CAsyncLogger::BackendAppenderDoLog(SLogMessage &incoming_log_msg) {
  for (auto& appender : appenders_) {
    if (appender->ShouldLog(incoming_log_msg.level)) {
      try {
        appender->Log(incoming_log_msg);
      } catch (const std::exception& ex) {
        DoErrHandler(ex.what());
      } catch (...) {
        DoErrHandler("Unknown exception in logger");
      }
    }
  }

  if (ShouldFlush(incoming_log_msg)) {
    BackendDoFlush();
  }
}

void CAsyncLogger::BackendDoFlush() {
  for (auto& appender : appenders_) {
    try {
      appender->Flush();
    } catch (const std::exception& ex) {
      DoErrHandler(ex.what());
    } catch (...) {
      DoErrHandler("Unknown exception in logger");
    }
  }
}

} // !namespace log
} // !namespace afcore